/*
 * Copyright 2011 Fabian Wenzelmann
 * 
 * This file is part of Recognition-Procedures-for-Boolean-Functions.
 * 
 * Recognition-Procedures-for-Boolean-Functions is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Recognition-Procedures-for-Boolean-Functions is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Recognition-Procedures-for-Boolean-Functions.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.wenzelmf.booleanFunction.lpb.combinatorial.solver;

import org.w3c.dom.Document;

import de.wenzelmf.booleanFunction.dnf.DNF;
import de.wenzelmf.booleanFunction.lpb.combinatorial.splittingTree.SplittingTree;
import de.wenzelmf.booleanFunction.lpb.combinatorial.splittingTree.SplittingTreeNode;
import de.wenzelmf.booleanFunction.lpb.combinatorial.splittingTree.TreeContext;
import de.wenzelmf.booleanFunction.parser.XMLDocumentException;
import de.wenzelmf.booleanFunction.util.IntegerValue;
import de.wenzelmf.booleanFunction.util.Tuple;

/**
 * Classes that implement this interface have three important jobs:
 * <ol>
 * 	<li>administrate the coefficients (set coefficient value and get coefficient value).</li>
 * 	<li>administrate the minimum and maximum degrees for all nodes in the tree.</li>
 * 	<li>Solve a conflict if a coefficient a<sub>k</sub> has to fulfill the following constraint:
 * x &lt; a<sub>k</sub> &lt; x + 1. In this case the solution cannot be an integer, but we can
 * solve this conflict to ensure that we can choose an integer afterwards. The easiest way to deal
 * with this problem is to double the complete system, this behavior is implemented in
 * {@link DoubleSolverInformation}.</li>
 * </ol>
 * 
 * @author Fabian Wenzelmann
 * @version 1.0
 *
 */
public interface SolverInformation
{
	/**
	 * Initialize this object (create all required objects...).
	 * 
	 * @param columns The columns in the table.
	 * @param dnf The DNF the tree has been created for.
	 * @param context The tree context that gives us information about the context of the tree.
	 * @param t The splitting tree itself.
	 */
	public void init(int columns, DNF dnf, TreeContext context, SplittingTree t);
	
	// TODO: ugly with this index... in another class they're not zero based...
	/**
	 * Return the coefficient in the specified column.
	 * 
	 * @param column The column in the table (a value <i>k</i> means that you should return the
	 * coefficient a<sub>k + 1</sub>.
	 * 
	 * @return a<sub>column + 1</sub>.
	 */
	public Integer getCoefficient(int column);
	/**
	 * Set the coefficient in the specified column.
	 * 
	 * @param column The column in the table (a value <i>k</i> means that you should set the
	 * coefficient a<sub>k + 1</sub>.
	 * @param value The new value of this coefficient.
	 * 
	 * @return The old value of a<sub>column + 1</sub>, if this value has not been set before
	 * {@code null}.
	 */
	public Integer setCoefficient(int column, int value);
	
	/**
	 * Return the pair (s, b) where s is the minimum degree of {@code n} and
	 * b is the maximum degree of {@code n}.
	 * 
	 * @param n The node to look for.
	 * 
	 * @return The pair (s, b) where s is the minimum degree of {@code n} and
	 * b is the maximum degree of {@code n}.
	 */
	public Tuple<IntegerValue, IntegerValue> getInterval(SplittingTreeNode n);
	
	/**
	 * Set the minimum degree of {@code n} to s and the maximum degree of {@code n} to b
	 * where (s, b) is the input tuple {@code value}.
	 * 
	 * @param n The node the minimum and maximum degree should be adjusted.
	 * @param value The new minimum and maximum degree of {@code n}.
	 * 
	 * @return The old minimum and maximum degree of {@code n}, {@code null} if this value has
	 * never been set.
	 */
	public Tuple<IntegerValue, IntegerValue> setInterval(SplittingTreeNode n, Tuple<IntegerValue, IntegerValue> value);
	
	/**
	 * If we have to choose the coefficient a<sub>k</sub> s.t. x &lt; a<sub>k</sub> &lt; x + 1
	 * there is a solution, but no integer solution, this method should solve the conflict
	 * and return the adjusted pair of min, max values.
	 *   
	 * @param column The column of the table where the error occurred.
	 * @param dnf The initial DNF.
	 * @param max The current max value.
	 * @param min The current min value.
	 * @param context The tree context (some additional information about the tree).
	 * @param t The tree itself.
	 * 
	 * @return The adjusted tuple (max', min') s.t. now an integer solution is possible.
	 */
	public Tuple<IntegerValue, IntegerValue> solveConflict(int column, DNF dnf, IntegerValue max, IntegerValue min, TreeContext context, SplittingTree t);
	
	/**
	 * This should return a XML document representing this solver information object.
	 * 
	 * If you implement this method you should also provide a parser somewhere to read the content again.
	 * See {@link de.wenzelmf.booleanFunction.parser.SolverInformationParser SolverInformationParser}
	 * for more information.
	 * 
	 * The tag name of the root node must be the value of {@link #TAG_NAME}. If you plan to right a parser
	 * for this class you must add an attribute with name {@link #TYPE_NAME} together with an unique
	 * name, have a look at the manual for reserved names.
	 * 
	 * @return A XML document representing this solver information.
	 * 
	 * @throws UnsupportedOperationException If this method is not supported by this class.
	 * @throws XMLDocumentException If there's any problem creating the document object.
	 */
	public Document toXMLDocument() throws UnsupportedOperationException, XMLDocumentException;
	
	/**
	 * That name of the root tag name that should be used in the XML root node when the
	 * {@link #toXMLDocument()} creates a XML document.
	 * 
	 * @see #toXMLDocument()
	 */
	public static final String TAG_NAME = "solverInformation";
	
	/**
	 * The name of the attribute the root node should have to identify the type of the SolverInformation
	 * when the {@link #toXMLDocument()} creates a XML document.
	 * 
	 * @see #toXMLDocument()
	 */
	public static final String TYPE_NAME = "type";

}
